feat: Multi-part missions and governor profiles#1082
feat: Multi-part missions and governor profiles#1082OH296 wants to merge 35 commits intoAdeptus-Dominus:mainfrom
Conversation
📝 WalkthroughWalkthroughA comprehensive overhaul of fleet event systems, planetary governance, and unit group mechanics. Introduces governor profiles, fleet event lifecycles, end-of-turn population dynamics, beast hunt missions with trophy delivery, and unit selection infrastructure whilst refactoring PlanetData to centralise state mutations and delegating fragmented logic to cohesive handlers. Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~75 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Cogitatio Incognitus, Tech-Priest. The machine spirits have processed thy submission. This compendium of modifications runs deep through the architecture—fleet events now carry persistent memory-logs, governors birth from the void with whispered identities, and planetary systems pulse with orchestrated lifecycle rhythms. The refactoring of PlanetData into a centralised authority over all terrestrial state represents a significant crystallisation of scattered imperatives into unified dogma. Caution: the removal of logging telemetry hath obscured potential diagnostic channels. Proceed with reverent scrutiny, for the interconnections are manifold and inscrutable. Pre-merge checks✅ Passed checks (3 passed)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 73
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (23)
scripts/scr_Table/scr_Table.gml (1)
96-99: CRITICAL MALFUNCTION DETECTED: Duplicate ritual invocation.The hover() subroutine is executed twice when the cursor sanctifies a row, Tech-Priest. Lines 96-99 constitute redundant logic—this code fragment must be purged, as the restructured input handling at lines 100-115 already encompasses this functionality.
Impact: Performance degradation and potential state corruption if hover() possesses side effects.
⚙️ Requisite ablation sequence
} - } - if (_row_entered && struct_exists(_row,"hover")){ - //show_debug_message($"click : {struct_exists(_row,"click_left")}"); - _row.hover(); - } - if (_row_entered){ + } + if (_row_entered){ if (struct_exists(_row,"hover")){objects/obj_controller/Draw_0.gml (1)
2-2: Ancient directive persists, Tech-Priest. Query: Shall I inscribe this task into the issue repository?The TODO annotation indicates unresolved labour—the transference of draw operations to the GUI layer awaits completion.
Wouldst thou desire the creation of a tracking issue for this architectural migration?
scripts/scr_specialist_training/scr_specialist_training.gml (2)
265-265: The sacred refactor pattern has been violated here, Tech-Priest.Whilst all other role invocations throughout this codex have been migrated to draw from the _roles array, this line still invokes the deprecated obj_ini.role[100,17] pattern. The _roles variable has been prepared at line 258, yet remains unutilised.
🔎 Rectification pattern for the inconsistency
-novice_type = string("{0} Aspirant",obj_ini.role[100,17]); +novice_type = string("{0} Aspirant",_roles[17]);
3-431: The machine spirit observes repeated invocations of active_roles(), Tech-Priest.This function is summoned six times across the specialist training rituals. Whilst each function's scope demands its own _roles binding, should active_roles() bear computational burden, consider passing _roles as a sacred parameter to the training functions rather than re-invoking the lookup ritual within each.
However, if active_roles() be but a simple array accessor, this pattern remains sound and maintainable.
scripts/scr_unit_quick_find_pane/scr_unit_quick_find_pane.gml (2)
448-448: Ambiguous equality operator, Tech-Priest. Verify the intent of this condition.The Machine Spirit detects
if (hide_sequence=30)— a single=within a conditional expression. In the arcane tongue of GML, this may evaluate as comparison, yet it invites confusion and potential error. If this is intended as equality check, the double sigil==is the sanctioned form for clarity.🔎 Proposed clarification
- if (hide_sequence=30) then hide_sequence=0; + if (hide_sequence==30) then hide_sequence=0;
128-231: Theupdate_mission_logfunction grows in complexity, Tech-Priest.The Machine Spirit notes that this function now handles multiple disparate data sources: planetary problems, controller quests, and fleet events. As new event types are added, consider whether extracting helper methods for each source type would preserve clarity and maintainability. The current implementation functions, but future expansion may warrant modularisation.
scripts/scr_struct_functions/scr_struct_functions.gml (1)
5-9: Ancient deprecated ritual awaits purging.Tech-Priest, this deprecated function-relic bears the mark of deletion yet persists in the codex. The comment-scroll proclaims its obsolescence—it but wraps
variable_clone()in vestigial ceremony.Would you have this Machine Spirit open a sacred tracking-issue in your repository's archives to ensure this expungement is not forgotten? Or shall we proceed to excise it forthwith?
scripts/scr_system_search_helpers/scr_system_search_helpers.gml (1)
186-197: Critical logic corruption detected, Tech-Priest. The data-spirits cry out in anguish.The conditional at lines 194-196 shall always evaluate true within this block, for
_types_sort(which guards entry at line 186) equalsarray_length(types). Thus, any star marked_add = trueby the loop shall be immediately overwritten tofalse. All stars with type filtering shall be rejected. This is a grievous malfunction.🔧 Proposed litany of correction
if (_add && _types_sort){ _add = false; for (var i=1;i<=planets;i++){ if (array_contains(types,p_type[i])){ _add = true; break; } } - if (array_length(types)){ - _add = false; - } }objects/obj_controller/Alarm_6.gml (3)
52-59: CRITICAL HERESY DETECTED — Assignment operator corrupts conditional logic, Tech-Priest.The Machine Spirit perceives a most grievous error. The single
=operator performs assignment, not comparison. This heretical construct shall:
- Overwrite
man[f]with"vehicle"for every iteration- Overwrite
ma_role[f]with each vehicle type string- Corrupt the sacred data arrays and produce erroneous vehicle counts
In GML, equality comparison requires
==or=only withinifparentheses when intended as comparison — but the current syntax is ambiguous and dangerous.🔧 Proposed sanctification of the code-runes
// sets up count for the vehicles // TODO This needs to be extended to accomodate the selection text like the man ones - if (man[f]="vehicle"){ + if (man[f]=="vehicle"){ vanz+=1; - if (ma_role[f]="Land Raider") then lrad+=1; - if (ma_role[f]="Rhino") then rhi+=1; - if (ma_role[f]="Predator") then pre+=1; - if (ma_role[f]="Land Speeder") then lspi+=1; - if (ma_role[f]="Whirlwind") then whi+=1; + if (ma_role[f]=="Land Raider") then lrad+=1; + if (ma_role[f]=="Rhino") then rhi+=1; + if (ma_role[f]=="Predator") then pre+=1; + if (ma_role[f]=="Land Speeder") then lspi+=1; + if (ma_role[f]=="Whirlwind") then whi+=1; }
85-89: Inconsistent data source for Librarian role designation, Tech-Priest.The Machine Spirit observes that this block still invokes
obj_ini.role[100,17]directly, whilst all other role references utilise the cached_rolesarray. This inconsistency violates the sanctified refactor pattern.🔧 Proposed harmonisation
if (lib>0){ - selecting_dudes+=string(lib)+" "+string(obj_ini.role[100,17]); + selecting_dudes+=string(lib)+" "+string(_roles[17]); if (lib>1) then selecting_dudes+="s"; selecting_dudes+=", "; }
214-214: CRITICAL HERESY — Assignment operator in conditional, Tech-Priest.The Machine Spirit detects assignment (
=) where comparison (==) is required. This construct shall:
- Assign
-1tosel_promoting- Evaluate as truthy (non-zero)
- Then immediately overwrite with
0The result:
sel_promotingis always set to0at this juncture, regardless of its prior state.🔧 Proposed sanctification
- if (sel_promoting=-1) then sel_promoting=0; + if (sel_promoting==-1) then sel_promoting=0;scripts/scr_event_code/scr_event_code.gml (1)
351-354: Inconsistent error pathway: exit versus return false.Tech-Priest, the default case still uses
exitwhilst line 323 usesreturn false. This inconsistency violates the principle of uniform behaviour. The function should returnfalsein all error paths.🔎 Proposed harmonisation
default: log_error("RE: Enemy, no faction could be chosen"); - exit; + return false;scripts/scr_buttons/scr_buttons.gml (1)
456-456: Unreachable code detected after return statement, Tech-Priest.The
pop_draw_return_values()invocation on line 456 exists beyond the conditional return statements (lines 451 and 454). This code shall never execute, leaving the draw state stack potentially corrupted.🔎 Excision of dead code
} else { pop_draw_return_values(); return false; } - pop_draw_return_values(); };scripts/scr_marine_struct/scr_marine_struct.gml (1)
2013-2031: Critical logic corruption detected in name_role function, Tech-Priest.The machine spirit perceives conflicting directives:
Line 2024: The string
"{temp_role} {name()}"lacks the sacred$prefix for template interpolation. This shall produce literal text rather than variable substitution.Line 2030: The return statement invokes
string("{0} {1}", temp_role, name()), discarding the_namevariable constructed with epithet data (lines 2024-2029). The epithet logic is rendered vestigial.🔎 Corrected logic pathway
static name_role = function(include_epithet = true) { var temp_role = role(); if (squad != "none") { if (struct_exists(obj_ini.squad_types[$ obj_ini.squads[squad].type], temp_role)) { var role_info = obj_ini.squad_types[$ obj_ini.squads[squad].type][$ temp_role]; if (struct_exists(role_info, "role")) { temp_role = role_info[$ "role"]; } } } - var _name = "{temp_role} {name()}"; + var _name = $"{temp_role} {name()}"; if (include_epithet){ if (array_length(epithets)){ _name += $" {epithets[0].title}"; } } - return string("{0} {1}", temp_role, name()); + return _name; };objects/obj_en_fleet/Alarm_1.gml (1)
10-10: Observation: TODO marker detected, Tech-Priest.This cogitator observes a TODO directive regarding the centralisation of orbiting logic. Dost thou wish this unit to generate an issue within the sacred archives of GitHub to track this pending rite of code refinement?
scripts/scr_enemy_ai_d/scr_enemy_ai_d.gml (1)
449-458: CRITICAL MALFUNCTION DETECTED, TECH-PRIEST!The machine spirit perceives a grievous error in the loop construct. The variable
planetis declared with value1, yet the loop conditioni<=planetsand incrementi++operate uponi- a variable from a prior loop scope. Furthermore,planetnever receives increment, causingsystem_garrison[planet]to eternally reference index1.This shall cause incorrect garrison processing and potentially undefined behaviour when
iexceedsplanets.🔎 Proposed corrective rite
// Local problems will go here var planet; - for (var planet=1;i<=planets;i++){ + for (var planet=1;planet<=planets;planet++){ if (i < array_length(system_garrison)){ - var garrison = system_garrison[planet]; + var garrison = system_garrison[planet]; if (garrison.garrison_force){ if (garrison.garrison_disposition_change(self,planet)!="none"){ dispo[planet]+=garrison.dispo_change; } } } }Additionally, line 450 should use
planetinstead ofifor the bounds check:- if (i < array_length(system_garrison)){ + if (planet < array_length(system_garrison)){scripts/scr_enemy_ai_a/scr_enemy_ai_a.gml (1)
248-263: default_imperium_attack ternary is dense; consider making the intent more explicitTech-Priest, this line encodes a non‑trivial doctrinal rule in a compact ternary:
default_imperium_attack = guard_score>0 && !((guard_score<=0.5) && (pdf_score>0)) ?"guard":"pdf";While correct, the nested condition and inline ternary are not immediately self‑evident to lesser adepts.
Would it aid future maintenance to extract the predicate into a named boolean, e.g.
var guard_preferred = ...;followed by a simplerif/else, so the choice between Guard and PDF becomes narratively clear in the code rather than encoded as a riddle?scripts/scr_enemy_ai_b/scr_enemy_ai_b.gml (1)
95-107: String interpolation and Low Gothic corruption detectedTech-Priest, the alert incantation at line 96 manifests two grievances:
- The string
"Planet {planet_numeral_name(i)} ..."lacketh the$prefix, rendering{planet_numeral_name(i)}as inert runes rather than executable function call.- The phrase
"has succeed ed"deviates from proper Gothic syntax; the correct declension is"seceded".Refactor to:
scr_alert("red", "owner", $"Planet {planet_numeral_name(i)} has seceded to the Tau Empire!", x, y);objects/obj_star/Create_0.gml (1)
64-76: Rectify the GovernorProfile array indexing to align with the 1-based planetary schemaTech-Priest, the initialisation of
p_governordeviates catastrophically from the established pattern. The array is first created with_planet_array_sizeentries, then obliterated and rebuilt witharray_push, yielding indices0..6(seven entries). Yet the rest of thy codebase accesses planets via 1-based indexing—when code invokesp_governor[planet]withplanet ∈ [1..8], it encounters a void at index 8, and the logic collapses into undefined darkness.All sibling arrays (
p_operatives,p_features, etc.) maintain the proper shape: nine slots indexed0..8, with indices1..8bearing data. Restorep_governorto this sanctified form:- p_governor = array_create(_planet_array_size, ""); + p_governor = array_create(_planet_array_size); - p_governor = []; - -for (var i=1;i<8;i++){ - array_push(p_governor, new GovernorProfile()); -} +for (var i = 1; i < _planet_array_size; i++){ + p_governor[i] = new GovernorProfile(); +}This ensures every planetary slot
1..8receives its GovernorProfile and prevents undefined memory access.scripts/scr_random_event/scr_random_event.gml (1)
644-679: Unreachable code detected, Tech-Priest.The cogitator's logic-pathways reveal a discrepancy most grave. Cases
10(Heretics) and13(Necron) at lines 666-675 shall never execute, for the enemy selection at line 646 invokes onlychoose(7,8,9). These xenos and heretical spawn remain forever dormant in the code-scriptures.Was this deliberate pruning of the enemy roster, or does the Machine Spirit sense an incomplete implementation?
scripts/scr_mission_functions/scr_mission_functions.gml (1)
990-1008: Critical logic error in add_new_problem function.Tech-Priest, a most grievous corruption exists at line 994. The condition
p_problem[planet][i] == timershould bep_problem[planet][i] == ""to find an empty slot. Currently, this seeks a slot containing the timer value, which will virtually never match, causing problems to never be added.🔎 Urgent correction required
if (star=="none"){ for (var i=0;i<array_length(p_problem[planet]);i++){ - if (p_problem[planet][i] == timer){ + if (p_problem[planet][i] == ""){ p_problem[planet][i]= problem; p_problem_other_data[planet][i]=other_data; p_timer[planet][i] = timer;scripts/scr_PlanetData/scr_PlanetData.gml (2)
557-563: Refactor: Sanctify this logic within a proper ritual, Tech-Priest.The machine spirit detects orphaned code-canticles within the constructor corpus. This population-zero reset logic dwells outside method boundaries, executing with each instantiation. Consider relocating this doctrine into
refresh_dataor a dedicated static purification method.⚙️ Proposed restructuring
Move this logic into a static method:
+ static purge_empty_planet_corruption = function(){ + if (population == 0) { + system.p_heresy[planet] = 0; + system.p_heresy_secret[planet] = 0; + for (var i = 0; i < array_length(system.p_influence[planet]); ++i) { + system.p_influence[planet][i] = 0; + } + } + }Then invoke within
refresh_dataor at the conclusion of population mutations.
324-554: Consider decomposition of complex ork growth ritual, Tech-Priest.The
grow_ork_forcesincantation spans 230 lines with multiple nested conditionals and repeated reassignment of the_randodesignation. The machine spirit suggests partitioning this ceremony into smaller sub-rituals:
- Ork population growth calculation
- Ork spreading mechanics
- Stronghold and Warboss evolution
- Fleet construction logic
- Waaagh departure sequence
This shall enhance clarity and ease future maintenance of the greenskin propagation algorithms.
📜 Review details
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (79)
ChapterMaster.yypobjects/obj_controller/Alarm_5.gmlobjects/obj_controller/Alarm_6.gmlobjects/obj_controller/CleanUp_0.gmlobjects/obj_controller/Draw_0.gmlobjects/obj_en_fleet/Alarm_1.gmlobjects/obj_en_fleet/Create_0.gmlobjects/obj_en_fleet/Destroy_0.gmlobjects/obj_en_fleet/Draw_0.gmlobjects/obj_en_fleet/Step_0.gmlobjects/obj_ncombat/Alarm_1.gmlobjects/obj_star/Create_0.gmlobjects/obj_star/Draw_0.gmlobjects/obj_star_select/Draw_64.gmlobjects/obj_timer/Create_0.gmlobjects/obj_turn_end/Alarm_1.gmlscripts/__init_global/__init_global.gmlscripts/action_draw_ellipse/action_draw_ellipse.gmlscripts/ds_map_helpers/ds_map_helpers.gmlscripts/ds_map_helpers/ds_map_helpers.yyscripts/instance_create/instance_create.gmlscripts/is_specialist/is_specialist.gmlscripts/scr_ChapterTraits/scr_ChapterTraits.gmlscripts/scr_PlanetData/scr_PlanetData.gmlscripts/scr_Table/scr_Table.gmlscripts/scr_UnitGroup_and_group_selection/scr_UnitGroup_and_group_selection.gmlscripts/scr_UnitGroup_and_group_selection/scr_UnitGroup_and_group_selection.yyscripts/scr_apothecary_ground/scr_apothecary_ground.gmlscripts/scr_buttons/scr_buttons.gmlscripts/scr_chapter_managent_events/scr_chapter_managent_events.gmlscripts/scr_cheatcode/scr_cheatcode.gmlscripts/scr_draw_planet_features/scr_draw_planet_features.gmlscripts/scr_draw_text/scr_draw_text.gmlscripts/scr_drop_select_function/scr_drop_select_function.gmlscripts/scr_enemy_ai_a/scr_enemy_ai_a.gmlscripts/scr_enemy_ai_b/scr_enemy_ai_b.gmlscripts/scr_enemy_ai_c/scr_enemy_ai_c.gmlscripts/scr_enemy_ai_d/scr_enemy_ai_d.gmlscripts/scr_enemy_ai_e/scr_enemy_ai_e.gmlscripts/scr_event_code/scr_event_code.gmlscripts/scr_fleet_events/scr_fleet_events.gmlscripts/scr_fleet_events/scr_fleet_events.yyscripts/scr_fleet_functions/scr_fleet_functions.gmlscripts/scr_forge_world_functions/scr_forge_world_functions.gmlscripts/scr_garrison/scr_garrison.gmlscripts/scr_governors/scr_governors.gmlscripts/scr_governors/scr_governors.yyscripts/scr_hit/scr_hit.gmlscripts/scr_imperial_navy_functions/scr_imperial_navy_functions.gmlscripts/scr_inquisition_mission/scr_inquisition_mission.gmlscripts/scr_khornate_fleet_functions/scr_khornate_fleet_functions.gmlscripts/scr_load_controller/scr_load_controller.gmlscripts/scr_marine_struct/scr_marine_struct.gmlscripts/scr_mechanicus_fleet_functions/scr_mechanicus_fleet_functions.gmlscripts/scr_mechanicus_fleet_functions/scr_mechanicus_fleet_functions.yyscripts/scr_mechanicus_missions/scr_mechanicus_missions.gmlscripts/scr_mission_functions/scr_mission_functions.gmlscripts/scr_ork_fleet_functions/scr_ork_fleet_functions.gmlscripts/scr_planetary_feature/scr_planetary_feature.gmlscripts/scr_player_fleet_functions/scr_player_fleet_functions.gmlscripts/scr_purge_world/scr_purge_world.gmlscripts/scr_random_event/scr_random_event.gmlscripts/scr_recruit_data/scr_recruit_data.gmlscripts/scr_roman_numerals/scr_roman_numerals.gmlscripts/scr_save_controller/scr_save_controller.gmlscripts/scr_shoot/scr_shoot.gmlscripts/scr_specialist_training/scr_specialist_training.gmlscripts/scr_string_functions/scr_string_functions.gmlscripts/scr_struct_functions/scr_struct_functions.gmlscripts/scr_system_search_helpers/scr_system_search_helpers.gmlscripts/scr_tau_fleet_functions/scr_tau_fleet_functions.gmlscripts/scr_tau_fleet_functions/scr_tau_fleet_functions.yyscripts/scr_trade/scr_trade.gmlscripts/scr_trade_dep/scr_trade_dep.gmlscripts/scr_ui_diplomacy/scr_ui_diplomacy.gmlscripts/scr_ui_manage/scr_ui_manage.gmlscripts/scr_unit_quick_find_pane/scr_unit_quick_find_pane.gmlsprites/spr_fleet_imperial/spr_fleet_imperial.yysprites/spr_fleet_tau/spr_fleet_tau.yy
💤 Files with no reviewable changes (12)
- scripts/scr_shoot/scr_shoot.gml
- scripts/scr_recruit_data/scr_recruit_data.gml
- scripts/scr_load_controller/scr_load_controller.gml
- scripts/scr_inquisition_mission/scr_inquisition_mission.gml
- scripts/scr_ui_diplomacy/scr_ui_diplomacy.gml
- scripts/scr_string_functions/scr_string_functions.gml
- scripts/is_specialist/is_specialist.gml
- scripts/scr_trade_dep/scr_trade_dep.gml
- objects/obj_turn_end/Alarm_1.gml
- objects/obj_timer/Create_0.gml
- scripts/scr_ChapterTraits/scr_ChapterTraits.gml
- scripts/scr_save_controller/scr_save_controller.gml
🧰 Additional context used
📓 Path-based instructions (3)
**/*.gml
⚙️ CodeRabbit configuration file
**/*.gml: - Constants ofmacrotype MUST have a space between the constant name and its value. Without it, the compiler will throw an error.
- WRONG:
#macro COLOR_RED11119- RIGHT:
#macro COLOR_RED 11119- Color codes in the code SHOULDN'T have any spaces in their ID.
- WRONG:
# 80bf40- RIGHT:
#80bf40- All code should comply with the up-to-date GML documentation.
Files:
scripts/__init_global/__init_global.gmlscripts/scr_mechanicus_missions/scr_mechanicus_missions.gmlscripts/scr_struct_functions/scr_struct_functions.gmlscripts/action_draw_ellipse/action_draw_ellipse.gmlobjects/obj_en_fleet/Destroy_0.gmlobjects/obj_en_fleet/Alarm_1.gmlscripts/ds_map_helpers/ds_map_helpers.gmlscripts/scr_mechanicus_fleet_functions/scr_mechanicus_fleet_functions.gmlscripts/scr_drop_select_function/scr_drop_select_function.gmlscripts/scr_specialist_training/scr_specialist_training.gmlobjects/obj_controller/CleanUp_0.gmlscripts/scr_trade/scr_trade.gmlscripts/scr_draw_text/scr_draw_text.gmlscripts/scr_fleet_functions/scr_fleet_functions.gmlscripts/scr_tau_fleet_functions/scr_tau_fleet_functions.gmlscripts/scr_enemy_ai_c/scr_enemy_ai_c.gmlscripts/scr_roman_numerals/scr_roman_numerals.gmlscripts/instance_create/instance_create.gmlscripts/scr_fleet_events/scr_fleet_events.gmlscripts/scr_buttons/scr_buttons.gmlscripts/scr_purge_world/scr_purge_world.gmlscripts/scr_hit/scr_hit.gmlscripts/scr_apothecary_ground/scr_apothecary_ground.gmlobjects/obj_star/Draw_0.gmlscripts/scr_planetary_feature/scr_planetary_feature.gmlscripts/scr_random_event/scr_random_event.gmlscripts/scr_player_fleet_functions/scr_player_fleet_functions.gmlscripts/scr_imperial_navy_functions/scr_imperial_navy_functions.gmlscripts/scr_UnitGroup_and_group_selection/scr_UnitGroup_and_group_selection.gmlscripts/scr_ork_fleet_functions/scr_ork_fleet_functions.gmlscripts/scr_enemy_ai_e/scr_enemy_ai_e.gmlobjects/obj_ncombat/Alarm_1.gmlobjects/obj_controller/Alarm_6.gmlobjects/obj_star/Create_0.gmlscripts/scr_ui_manage/scr_ui_manage.gmlobjects/obj_star_select/Draw_64.gmlscripts/scr_draw_planet_features/scr_draw_planet_features.gmlobjects/obj_en_fleet/Step_0.gmlscripts/scr_Table/scr_Table.gmlscripts/scr_governors/scr_governors.gmlscripts/scr_chapter_managent_events/scr_chapter_managent_events.gmlscripts/scr_unit_quick_find_pane/scr_unit_quick_find_pane.gmlobjects/obj_en_fleet/Create_0.gmlscripts/scr_system_search_helpers/scr_system_search_helpers.gmlscripts/scr_marine_struct/scr_marine_struct.gmlobjects/obj_en_fleet/Draw_0.gmlscripts/scr_garrison/scr_garrison.gmlscripts/scr_enemy_ai_d/scr_enemy_ai_d.gmlobjects/obj_controller/Alarm_5.gmlscripts/scr_PlanetData/scr_PlanetData.gmlscripts/scr_enemy_ai_a/scr_enemy_ai_a.gmlscripts/scr_event_code/scr_event_code.gmlscripts/scr_forge_world_functions/scr_forge_world_functions.gmlscripts/scr_khornate_fleet_functions/scr_khornate_fleet_functions.gmlscripts/scr_enemy_ai_b/scr_enemy_ai_b.gmlscripts/scr_mission_functions/scr_mission_functions.gmlscripts/scr_cheatcode/scr_cheatcode.gmlobjects/obj_controller/Draw_0.gml
**/*.*
⚙️ CodeRabbit configuration file
**/*.*: - Do not prioritize the shortest code. Prioritize code that explicitly reveals its intent.
- Understandable variable naming is extremely important.
- If a solution is "clever" but hard to parse mentally, request a refactor to a more verbose but clearer approach.
- Apply the "Rule of Three": suggest abstraction when logic is repeated three times or more times.
- For subjective improvements (naming, architectural choice), do not give a concrete suggestion immediately. Instead, ask a guiding question to prompt the user's reflection.
- Every suggestion for a code change must include a brief justification.
- If a TODO comment is added, ask the user if you should create a GitHub issue for this TODO.
- If a TODO comment is deleted, remind the user if there is an active GitHub issue related to that comment.
Files:
scripts/__init_global/__init_global.gmlscripts/scr_mechanicus_missions/scr_mechanicus_missions.gmlscripts/scr_struct_functions/scr_struct_functions.gmlscripts/scr_fleet_events/scr_fleet_events.yyscripts/action_draw_ellipse/action_draw_ellipse.gmlobjects/obj_en_fleet/Destroy_0.gmlobjects/obj_en_fleet/Alarm_1.gmlscripts/ds_map_helpers/ds_map_helpers.yyscripts/ds_map_helpers/ds_map_helpers.gmlscripts/scr_mechanicus_fleet_functions/scr_mechanicus_fleet_functions.gmlscripts/scr_drop_select_function/scr_drop_select_function.gmlsprites/spr_fleet_tau/spr_fleet_tau.yyscripts/scr_specialist_training/scr_specialist_training.gmlobjects/obj_controller/CleanUp_0.gmlscripts/scr_trade/scr_trade.gmlscripts/scr_draw_text/scr_draw_text.gmlscripts/scr_fleet_functions/scr_fleet_functions.gmlscripts/scr_tau_fleet_functions/scr_tau_fleet_functions.gmlscripts/scr_enemy_ai_c/scr_enemy_ai_c.gmlscripts/scr_roman_numerals/scr_roman_numerals.gmlscripts/instance_create/instance_create.gmlscripts/scr_fleet_events/scr_fleet_events.gmlscripts/scr_buttons/scr_buttons.gmlscripts/scr_purge_world/scr_purge_world.gmlscripts/scr_hit/scr_hit.gmlscripts/scr_apothecary_ground/scr_apothecary_ground.gmlobjects/obj_star/Draw_0.gmlscripts/scr_mechanicus_fleet_functions/scr_mechanicus_fleet_functions.yyscripts/scr_planetary_feature/scr_planetary_feature.gmlscripts/scr_random_event/scr_random_event.gmlscripts/scr_player_fleet_functions/scr_player_fleet_functions.gmlscripts/scr_imperial_navy_functions/scr_imperial_navy_functions.gmlscripts/scr_UnitGroup_and_group_selection/scr_UnitGroup_and_group_selection.gmlscripts/scr_ork_fleet_functions/scr_ork_fleet_functions.gmlscripts/scr_enemy_ai_e/scr_enemy_ai_e.gmlobjects/obj_ncombat/Alarm_1.gmlobjects/obj_controller/Alarm_6.gmlobjects/obj_star/Create_0.gmlscripts/scr_ui_manage/scr_ui_manage.gmlobjects/obj_star_select/Draw_64.gmlscripts/scr_draw_planet_features/scr_draw_planet_features.gmlobjects/obj_en_fleet/Step_0.gmlscripts/scr_Table/scr_Table.gmlscripts/scr_governors/scr_governors.gmlscripts/scr_chapter_managent_events/scr_chapter_managent_events.gmlscripts/scr_unit_quick_find_pane/scr_unit_quick_find_pane.gmlobjects/obj_en_fleet/Create_0.gmlscripts/scr_system_search_helpers/scr_system_search_helpers.gmlscripts/scr_marine_struct/scr_marine_struct.gmlChapterMaster.yypobjects/obj_en_fleet/Draw_0.gmlscripts/scr_garrison/scr_garrison.gmlsprites/spr_fleet_imperial/spr_fleet_imperial.yyscripts/scr_enemy_ai_d/scr_enemy_ai_d.gmlobjects/obj_controller/Alarm_5.gmlscripts/scr_UnitGroup_and_group_selection/scr_UnitGroup_and_group_selection.yyscripts/scr_PlanetData/scr_PlanetData.gmlscripts/scr_enemy_ai_a/scr_enemy_ai_a.gmlscripts/scr_event_code/scr_event_code.gmlscripts/scr_forge_world_functions/scr_forge_world_functions.gmlscripts/scr_khornate_fleet_functions/scr_khornate_fleet_functions.gmlscripts/scr_enemy_ai_b/scr_enemy_ai_b.gmlscripts/scr_governors/scr_governors.yyscripts/scr_mission_functions/scr_mission_functions.gmlscripts/scr_cheatcode/scr_cheatcode.gmlscripts/scr_tau_fleet_functions/scr_tau_fleet_functions.yyobjects/obj_controller/Draw_0.gml
**/*.yy
⚙️ CodeRabbit configuration file
**/*.yy: 1. When any script or sprite.yyfiles are deleted, their paths should also be deleted from the project.yypfile, otherwise the game will crash.
2. When any script or sprite.yyfiles are created, their paths should be added to the project.yypfile, otherwise they'll fail.
Files:
scripts/scr_fleet_events/scr_fleet_events.yyscripts/ds_map_helpers/ds_map_helpers.yysprites/spr_fleet_tau/spr_fleet_tau.yyscripts/scr_mechanicus_fleet_functions/scr_mechanicus_fleet_functions.yysprites/spr_fleet_imperial/spr_fleet_imperial.yyscripts/scr_UnitGroup_and_group_selection/scr_UnitGroup_and_group_selection.yyscripts/scr_governors/scr_governors.yyscripts/scr_tau_fleet_functions/scr_tau_fleet_functions.yy
🧠 Learnings (19)
📚 Learning: 2025-09-04T14:37:58.773Z
Learnt from: CR
Repo: Adeptus-Dominus/ChapterMaster PR: 0
File: docs/CODE_STYLE.md:0-0
Timestamp: 2025-09-04T14:37:58.773Z
Learning: Applies to docs/**/*.gml : File names should follow GameMaker type-prefix conventions
Applied to files:
scripts/scr_fleet_events/scr_fleet_events.yyscripts/scr_tau_fleet_functions/scr_tau_fleet_functions.yy
📚 Learning: 2025-09-04T14:37:58.773Z
Learnt from: CR
Repo: Adeptus-Dominus/ChapterMaster PR: 0
File: docs/CODE_STYLE.md:0-0
Timestamp: 2025-09-04T14:37:58.773Z
Learning: Applies to docs/**/scr_*_functions.gml : Prefer storing scripts in library-like files named scr_*_functions.gml
Applied to files:
scripts/scr_fleet_events/scr_fleet_events.yyscripts/scr_drop_select_function/scr_drop_select_function.gmlscripts/scr_fleet_events/scr_fleet_events.gmlscripts/scr_buttons/scr_buttons.gmlscripts/scr_mechanicus_fleet_functions/scr_mechanicus_fleet_functions.yyscripts/scr_chapter_managent_events/scr_chapter_managent_events.gmlChapterMaster.yypscripts/scr_UnitGroup_and_group_selection/scr_UnitGroup_and_group_selection.yyscripts/scr_governors/scr_governors.yyscripts/scr_tau_fleet_functions/scr_tau_fleet_functions.yy
📚 Learning: 2025-03-31T23:32:30.003Z
Learnt from: OH296
Repo: Adeptus-Dominus/ChapterMaster PR: 646
File: objects/obj_pnunit/Alarm_5.gml:84-91
Timestamp: 2025-03-31T23:32:30.003Z
Learning: In obj_pnunit/Alarm_5.gml, the function get_armour_data("maintenance") will always return a numeric value (at minimum 0), making null/undefined checks unnecessary.
Applied to files:
objects/obj_en_fleet/Alarm_1.gmlobjects/obj_ncombat/Alarm_1.gmlobjects/obj_controller/Alarm_6.gmlobjects/obj_controller/Alarm_5.gml
📚 Learning: 2025-03-31T15:41:45.611Z
Learnt from: EttyKitty
Repo: Adeptus-Dominus/ChapterMaster PR: 649
File: objects/obj_enunit/Alarm_0.gml:289-291
Timestamp: 2025-03-31T15:41:45.611Z
Learning: GameMaker Studio's function `action_if_variable(image_index, -500, 0)` is auto-generated code from GameMaker's visual Drag and Drop system. It checks if image_index equals -500. In ChapterMaster, this was being used as a special flag for enemy unit movement, but wasn't triggering consistently, causing enemies to move only every other turn. The refactored code replaced this with direct function calls at specific combat stages.
Applied to files:
objects/obj_en_fleet/Alarm_1.gmlscripts/scr_enemy_ai_c/scr_enemy_ai_c.gmlscripts/scr_player_fleet_functions/scr_player_fleet_functions.gmlscripts/scr_imperial_navy_functions/scr_imperial_navy_functions.gmlobjects/obj_en_fleet/Step_0.gmlobjects/obj_en_fleet/Draw_0.gmlscripts/scr_enemy_ai_d/scr_enemy_ai_d.gml
📚 Learning: 2025-03-31T15:41:45.611Z
Learnt from: EttyKitty
Repo: Adeptus-Dominus/ChapterMaster PR: 649
File: objects/obj_enunit/Alarm_0.gml:289-291
Timestamp: 2025-03-31T15:41:45.611Z
Learning: GameMaker Studio's function `action_if_variable(image_index, -500, 0)` was part of an old enemy movement system in ChapterMaster. This syntax is auto-generated from GameMaker's Drag-and-Drop interface and checks if image_index is greater than or equal to -500. In the refactored code, enemy movement is triggered directly through function calls rather than relying on this conditional check.
Applied to files:
objects/obj_en_fleet/Alarm_1.gmlobjects/obj_en_fleet/Step_0.gmlscripts/scr_enemy_ai_d/scr_enemy_ai_d.gml
📚 Learning: 2025-03-07T01:56:40.971Z
Learnt from: MCPO-Spartan-117
Repo: Adeptus-Dominus/ChapterMaster PR: 562
File: scripts/scr_marine_struct/scr_marine_struct.gml:0-0
Timestamp: 2025-03-07T01:56:40.971Z
Learning: Marines' ages should be incremented at the year transition in obj_turn_end/Alarm_1.gml rather than calculated dynamically based on the current year and recruitment date. This ensures proper aging without retroactive application.
Applied to files:
objects/obj_en_fleet/Alarm_1.gmlscripts/scr_specialist_training/scr_specialist_training.gmlobjects/obj_ncombat/Alarm_1.gmlobjects/obj_controller/Alarm_6.gmlobjects/obj_controller/Alarm_5.gml
📚 Learning: 2025-04-15T10:54:19.720Z
Learnt from: VanWeapon
Repo: Adeptus-Dominus/ChapterMaster PR: 725
File: scripts/scr_special_view/scr_special_view.gml:49-49
Timestamp: 2025-04-15T10:54:19.720Z
Learning: In the ChapterMaster codebase, obj_ini.role[100][2] and obj_ini.role[100][eROLE.ChapterMaster] reference different roles, and both are needed in conditions checking for specific types of units. Numeric indices should not be assumed to match their corresponding enum values without verification.
Applied to files:
scripts/scr_specialist_training/scr_specialist_training.gmlobjects/obj_ncombat/Alarm_1.gmlobjects/obj_controller/Alarm_6.gmlobjects/obj_controller/Alarm_5.gml
📚 Learning: 2025-02-24T07:38:42.267Z
Learnt from: MCPO-Spartan-117
Repo: Adeptus-Dominus/ChapterMaster PR: 508
File: scripts/scr_specialist_training/scr_specialist_training.gml:371-371
Timestamp: 2025-02-24T07:38:42.267Z
Learning: The spec_train_data array index for Techmarine training data is 0, as confirmed by the maintainer.
Applied to files:
scripts/scr_specialist_training/scr_specialist_training.gml
📚 Learning: 2025-09-04T14:37:58.773Z
Learnt from: CR
Repo: Adeptus-Dominus/ChapterMaster PR: 0
File: docs/CODE_STYLE.md:0-0
Timestamp: 2025-09-04T14:37:58.773Z
Learning: Applies to docs/**/*.gml : Prefer a group prefix at the start of function/script names (e.g., string_convert, fleet_explode)
Applied to files:
scripts/scr_fleet_events/scr_fleet_events.gmlscripts/scr_mechanicus_fleet_functions/scr_mechanicus_fleet_functions.yyscripts/scr_UnitGroup_and_group_selection/scr_UnitGroup_and_group_selection.gmlscripts/scr_UnitGroup_and_group_selection/scr_UnitGroup_and_group_selection.yy
📚 Learning: 2025-09-04T14:52:45.005Z
Learnt from: OH296
Repo: Adeptus-Dominus/ChapterMaster PR: 0
File: :0-0
Timestamp: 2025-09-04T14:52:45.005Z
Learning: Project coding style summary:
- Constructors PascalCase; functions/variables snake_case with group prefixes (scr_*).
- Enums: enum name eNAME in SNAKE_CASE; entries PascalCase.
- Macros: ALL_CAPS SNAKE_CASE.
- Indentation 4 spaces; semicolons; use &&/||; parentheses for mixed ops; prefer ++/--.
- Prefer template strings $"..."; use “///” doc comments.
- Locals recommended with leading underscore.
- Organize scripts into library-like files; use early returns and init vars at declaration.
Applied to files:
scripts/scr_buttons/scr_buttons.gmlscripts/scr_UnitGroup_and_group_selection/scr_UnitGroup_and_group_selection.yy
📚 Learning: 2025-06-16T17:12:13.045Z
Learnt from: EttyKitty
Repo: Adeptus-Dominus/ChapterMaster PR: 878
File: scripts/scr_culture_visuals/scr_culture_visuals.gml:1256-1352
Timestamp: 2025-06-16T17:12:13.045Z
Learning: In scripts/scr_culture_visuals/scr_culture_visuals.gml, the weapon visual data declarations contain known DRY violations that are acknowledged by the development team but deferred to future refactoring efforts rather than addressed in individual feature PRs.
Applied to files:
scripts/scr_buttons/scr_buttons.gml
📚 Learning: 2025-04-18T13:33:54.167Z
Learnt from: EttyKitty
Repo: Adeptus-Dominus/ChapterMaster PR: 0
File: :0-0
Timestamp: 2025-04-18T13:33:54.167Z
Learning: In obj_new_button/Step_0.gml, when using scr_click_left() for detecting clicks on menu buttons, it should be called with parameter 0 (scr_click_left(0)) to disable the default cooldown of 60 steps. Using the default cooldown can cause menu buttons to appear unresponsive since it prevents subsequent clicks from being detected.
Applied to files:
scripts/scr_hit/scr_hit.gmlobjects/obj_controller/Draw_0.gml
📚 Learning: 2025-04-18T19:18:34.387Z
Learnt from: EttyKitty
Repo: Adeptus-Dominus/ChapterMaster PR: 734
File: objects/obj_creation/Draw_0.gml:765-771
Timestamp: 2025-04-18T19:18:34.387Z
Learning: When refactoring mouse input in ChapterMaster, prefer using the `point_and_click([x1, y1, x2, y2])` function rather than `scr_click_left(0)` for UI elements. Setting a cooldown of 0 is problematic as it removes click protection, whereas `point_and_click()` uses a default cooldown of 60 and combines rectangle bounds checking with click detection.
Applied to files:
scripts/scr_hit/scr_hit.gml
📚 Learning: 2025-03-20T22:22:57.319Z
Learnt from: EttyKitty
Repo: Adeptus-Dominus/ChapterMaster PR: 0
File: :0-0
Timestamp: 2025-03-20T22:22:57.319Z
Learning: In the ChapterMaster game PR #424, the psychic power system was changed to be data-driven, with perils now able to occur on both successful and failed casts but with reduced frequency overall.
Applied to files:
scripts/scr_random_event/scr_random_event.gmlChapterMaster.yyp
📚 Learning: 2025-03-11T01:34:29.268Z
Learnt from: EttyKitty
Repo: Adeptus-Dominus/ChapterMaster PR: 579
File: objects/obj_enunit/Alarm_0.gml:186-187
Timestamp: 2025-03-11T01:34:29.268Z
Learning: In the ChapterMaster game, the variable `_column_size_value` represents the physical size/mass of a column of units, calculated as (vehicles * 2.5) + (dreadnoughts * 2) + (men * 0.5), and is used for determining back row protection rules.
Applied to files:
objects/obj_controller/Alarm_6.gml
📚 Learning: 2025-04-16T09:51:55.065Z
Learnt from: EttyKitty
Repo: Adeptus-Dominus/ChapterMaster PR: 0
File: :0-0
Timestamp: 2025-04-16T09:51:55.065Z
Learning: In obj_ingame_menu/Step_0.gml, the line "if (effect=14){instance_create(0,0,obj_fade);fading=0.1;}" must not be commented out, as it's critical for menu button transitions. When clicking the Exit button, it sets effect=14, but without this handler creating the fade effect object, no transition occurs.
Applied to files:
scripts/scr_draw_planet_features/scr_draw_planet_features.gmlobjects/obj_en_fleet/Draw_0.gmlobjects/obj_controller/Draw_0.gml
📚 Learning: 2025-03-01T11:06:25.427Z
Learnt from: MCPO-Spartan-117
Repo: Adeptus-Dominus/ChapterMaster PR: 526
File: objects/obj_popup/Draw_0.gml:234-239
Timestamp: 2025-03-01T11:06:25.427Z
Learning: The comment "Need to modify ^^^^ based on if it is chaos or daemonic" in the artifact gifting code is intentionally kept as a reminder that this implementation is not yet finished, despite the significant refactoring already done.
Applied to files:
scripts/scr_event_code/scr_event_code.gml
📚 Learning: 2025-09-04T14:37:58.773Z
Learnt from: CR
Repo: Adeptus-Dominus/ChapterMaster PR: 0
File: docs/CODE_STYLE.md:0-0
Timestamp: 2025-09-04T14:37:58.773Z
Learning: Applies to docs/**/*.gml : Avoid creating a separate file for every small script
Applied to files:
scripts/scr_governors/scr_governors.yy
📚 Learning: 2025-04-15T10:51:31.955Z
Learnt from: VanWeapon
Repo: Adeptus-Dominus/ChapterMaster PR: 725
File: datafiles/main/chapters/10.JSON:281-346
Timestamp: 2025-04-15T10:51:31.955Z
Learning: GameMaker Language (GML) JSON parser accepts trailing commas in JSON files, unlike standard JSON parsers which consider them syntax errors. When reviewing JSON files in this codebase, trailing commas should not be flagged as issues.
Applied to files:
scripts/scr_tau_fleet_functions/scr_tau_fleet_functions.yy
| if (champ>0){ | ||
| selecting_dudes+=$"{champ} {obj_ini.role[100][eROLE.Ancient]}"; | ||
| selecting_dudes+=$"{champ} {_roles[eROLE.Ancient]}"; | ||
| if (chap>1) then selecting_dudes+="s"; | ||
| selecting_dudes+=", "; | ||
| } |
There was a problem hiding this comment.
Logic corruption in Ancient pluralisation, Tech-Priest.
The Machine Spirit detects a transcription error. The block assembles text for champ (Ancient count), yet line 77 inspects chap (Chaplain count) for pluralisation. This shall produce incorrect grammar when multiple Ancients are selected.
🔧 Proposed correction
if (champ>0){
selecting_dudes+=$"{champ} {_roles[eROLE.Ancient]}";
- if (chap>1) then selecting_dudes+="s";
+ if (champ>1) then selecting_dudes+="s";
selecting_dudes+=", ";
}🤖 Prompt for AI Agents
In objects/obj_controller/Alarm_6.gml around lines 75 to 79, the pluralisation
check uses the wrong variable (`chap`) when appending an "s" for Ancients;
change the conditional to test `champ>1` (the Ancient count) so the string
correctly becomes plural when multiple Ancients are selected, and keep the rest
of the concatenation logic as-is.
| if (assa>0){ | ||
| selecting_dudes+=string(assa)+" "+string(obj_ini.role[100][eROLE.Assault]); | ||
| selecting_dudes+=string(assa)+" "+string(_roles[eROLE.Assault]); | ||
| if (sgt>1) then selecting_dudes+="s"; | ||
| selecting_dudes+=", "; | ||
| } |
There was a problem hiding this comment.
Logic corruption in Assault pluralisation, Tech-Priest.
The Machine Spirit perceives another transcription error. The block assembles text for assa (Assault count), yet line 137 inspects sgt (Sergeant count) for pluralisation.
🔧 Proposed correction
if (assa>0){
selecting_dudes+=string(assa)+" "+string(_roles[eROLE.Assault]);
- if (sgt>1) then selecting_dudes+="s";
+ if (assa>1) then selecting_dudes+="s";
selecting_dudes+=", ";
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if (assa>0){ | |
| selecting_dudes+=string(assa)+" "+string(obj_ini.role[100][eROLE.Assault]); | |
| selecting_dudes+=string(assa)+" "+string(_roles[eROLE.Assault]); | |
| if (sgt>1) then selecting_dudes+="s"; | |
| selecting_dudes+=", "; | |
| } | |
| if (assa>0){ | |
| selecting_dudes+=string(assa)+" "+string(_roles[eROLE.Assault]); | |
| if (assa>1) then selecting_dudes+="s"; | |
| selecting_dudes+=", "; | |
| } |
🤖 Prompt for AI Agents
In objects/obj_controller/Alarm_6.gml around lines 135 to 139, the pluralisation
check incorrectly tests `sgt` when building the Assault text fragment; change
the conditional to test `assa` (e.g., if (assa>1) then ...) so the "s" is added
based on the Assault count, and keep the rest of the string assembly unchanged.
| if (temp<200) and (sgts>0){ | ||
| if (techmarines=1) then p2+=string(techmarines)+" "+string(obj_ini.role[100][18])+", "; | ||
| if (techmarines>1) then p2+=string(techmarines)+" "+string(obj_ini.role[100][18])+", "; | ||
| if (techmarines=1) then p2+=string(techmarines)+" "+string(_roles[18])+", "; | ||
| if (techmarines>1) then p2+=string(techmarines)+" "+string(_roles[18])+", "; | ||
| } | ||
| if (temp<200) and (vet_sgts>0){ | ||
| if (techmarines=1) then p2+=string(techmarines)+" "+string(obj_ini.role[100][19])+", "; | ||
| if (techmarines>1) then p2+=string(techmarines)+" "+string(obj_ini.role[100][19])+", "; | ||
| if (techmarines=1) then p2+=string(techmarines)+" "+string(_roles[19])+", "; | ||
| if (techmarines>1) then p2+=string(techmarines)+" "+string(_roles[19])+", "; | ||
| } |
There was a problem hiding this comment.
CRITICAL LOGIC CORRUPTION DETECTED — Variable mismatch in Sergeant role display, Tech-Priest.
The Machine Spirit perceives a grievous transcription error. The outer conditions inspect sgts and vet_sgts, yet the inner logic references techmarines for both the count comparison and the displayed value. This heresy shall produce erroneous battle narrative output.
🔧 Proposed sanctification of the code-runes
if (temp<200) and (sgts>0){
- if (techmarines=1) then p2+=string(techmarines)+" "+string(_roles[18])+", ";
- if (techmarines>1) then p2+=string(techmarines)+" "+string(_roles[18])+", ";
+ if (sgts=1) then p2+=string(sgts)+" "+string(_roles[18])+", ";
+ if (sgts>1) then p2+=string(sgts)+" "+string(_roles[18])+", ";
}
if (temp<200) and (vet_sgts>0){
- if (techmarines=1) then p2+=string(techmarines)+" "+string(_roles[19])+", ";
- if (techmarines>1) then p2+=string(techmarines)+" "+string(_roles[19])+", ";
+ if (vet_sgts=1) then p2+=string(vet_sgts)+" "+string(_roles[19])+", ";
+ if (vet_sgts>1) then p2+=string(vet_sgts)+" "+string(_roles[19])+", ";
}🤖 Prompt for AI Agents
In objects/obj_ncombat/Alarm_1.gml around lines 182 to 189, the inner
conditionals mistakenly reference techmarines instead of the sergeant counters;
replace occurrences of techmarines with sgts in the first block and with
vet_sgts in the second block, and use the correct equality/comparison operators
for the singular (== 1) and plural (> 1) checks, appending the corresponding
sgts/vet_sgts value with the appropriate _roles index so the displayed counts
and role names match the outer conditions.
| function draw_circle_with_outline_width(xx,yy,r,w){ | ||
| for (var i=0.0;i<w;i+=0.1){ | ||
| draw_circle(xx,yy,r+i,1); | ||
| } | ||
| } |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
A new rendering rite has been inscribed, Tech-Priest.
The draw_circle_with_outline_width function manifests outline effects through iterative circle rendering. The machine spirits observe:
- The 0.1 increment creates 10×w draw calls per invocation. For substantial width values, this may burden the rendering pipeline.
- No documentation enlightens future Tech-Priests on the function's sacred purpose or parameter meanings.
- The function assumes external configuration of draw colour and alpha state.
⚙️ Proposed improvements
+/// @desc Draws a circle with an outline of specified width by rendering concentric circles
+/// @param {real} xx - X coordinate of circle centre
+/// @param {real} yy - Y coordinate of circle centre
+/// @param {real} r - Inner radius
+/// @param {real} w - Outline width
function draw_circle_with_outline_width(xx,yy,r,w){
for (var i=0.0;i<w;i+=0.1){
draw_circle(xx,yy,r+i,1);
}
}Consider documenting the performance implications when width exceeds modest values. The rendering spirits favour fewer, bolder strokes over many whispers.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| function draw_circle_with_outline_width(xx,yy,r,w){ | |
| for (var i=0.0;i<w;i+=0.1){ | |
| draw_circle(xx,yy,r+i,1); | |
| } | |
| } | |
| /// @desc Draws a circle with an outline of specified width by rendering concentric circles | |
| /// @param {real} xx - X coordinate of circle centre | |
| /// @param {real} yy - Y coordinate of circle centre | |
| /// @param {real} r - Inner radius | |
| /// @param {real} w - Outline width | |
| function draw_circle_with_outline_width(xx,yy,r,w){ | |
| for (var i=0.0;i<w;i+=0.1){ | |
| draw_circle(xx,yy,r+i,1); | |
| } | |
| } |
🤖 Prompt for AI Agents
In scripts/action_draw_ellipse/action_draw_ellipse.gml around lines 27-31, the
draw_circle_with_outline_width function uses a 0.1 increment which causes ~10*w
draw calls and can severely hurt performance for large widths; update the
function to (1) document its purpose and parameters at the top (what xx, yy, r,
w mean and that color/alpha must be set externally), (2) clamp/limit w to a
sensible maximum (e.g., max_w) and replace the 0.1 loop step with a coarser
configurable step (or compute iterations = max(1, ceil(w/step))) so you do far
fewer draw calls, and (3) optionally add an extra parameter for step or
maxIterations so callers can request higher fidelity when needed; keep
color/alpha management documented (or explicitly save/restore draw state if you
choose to manage it inside the function).
| function instance_at_location(xx,yy,obj_type){ | ||
| var _nearest = instance_nearest(xx, yy, obj_type); | ||
| return (_nearest.x == xx && _nearest.y == yy) ? _nearest : noone; | ||
| } |
There was a problem hiding this comment.
Warning: Null instance access may corrupt the Machine Spirit.
Tech-Priest, should no instances of obj_type exist within the materium, instance_nearest shall return noone. Accessing noone.x invokes undefined behaviour—a heresy most dire.
🔎 Proposed sanctification with null guard
function instance_at_location(xx,yy,obj_type){
var _nearest = instance_nearest(xx, yy, obj_type);
+ if (_nearest == noone) return noone;
return (_nearest.x == xx && _nearest.y == yy) ? _nearest : noone;
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| function instance_at_location(xx,yy,obj_type){ | |
| var _nearest = instance_nearest(xx, yy, obj_type); | |
| return (_nearest.x == xx && _nearest.y == yy) ? _nearest : noone; | |
| } | |
| function instance_at_location(xx,yy,obj_type){ | |
| var _nearest = instance_nearest(xx, yy, obj_type); | |
| if (_nearest == noone) return noone; | |
| return (_nearest.x == xx && _nearest.y == yy) ? _nearest : noone; | |
| } |
🤖 Prompt for AI Agents
In scripts/instance_create/instance_create.gml around lines 27-30, the code
dereferences a possibly null instance by accessing _nearest.x/_nearest.y without
checking for noone; change the logic to first check if _nearest == noone and
immediately return noone if so, otherwise compare _nearest.x and _nearest.y with
xx/yy and return _nearest or noone accordingly to avoid undefined behavior.
| if (_conditions.end_loop){ | ||
| break; | ||
| } | ||
| _unit=fetch_unit([com,i]); |
There was a problem hiding this comment.
Inconsistent variable naming within loop, Tech-Priest.
Line 13 declares unit but line 47 assigns to _unit. This creates an implicit global variable rather than using the declared local.
🔎 Harmonised variable naming
- _unit=fetch_unit([com,i]);
+ unit=fetch_unit([com,i]);
- if (_conditions.evaluate(_unit)){
- array_push(_units, _unit);
+ if (_conditions.evaluate(unit)){
+ array_push(_units, unit);
}Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In
scripts/scr_UnitGroup_and_group_selection/scr_UnitGroup_and_group_selection.gml
around line 47, the loop assigns to _unit while the local variable was declared
as unit earlier, causing an implicit global; change the assignment to use the
declared local variable name (unit = fetch_unit([com,i])) or, if the underscore
name is intended, update the declaration to match (_unit) and ensure it is
declared local with var/let at its declaration site so no implicit globals are
created.
| var _add = true; | ||
| if (group!="all"){ | ||
| var _group = group; | ||
| if (group_is_array){ |
There was a problem hiding this comment.
Variable identifier mismatch detected, Tech-Priest.
The condition references group_is_array but the variable established on line 69 is group_is_complex. This shall evaluate as undefined.
🔎 Corrected identifier
- if (group_is_array){
+ if (group_is_complex){📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if (group_is_array){ | |
| if (group_is_complex){ |
🤖 Prompt for AI Agents
In
scripts/scr_UnitGroup_and_group_selection/scr_UnitGroup_and_group_selection.gml
around line 119, the if condition uses the undefined identifier "group_is_array"
while the flag was declared as "group_is_complex" on line 69; update the
condition to use the correct variable name (change "group_is_array" to
"group_is_complex") or, if the intended semantics require an "array" flag,
rename the declaration at line 69 to "group_is_array" so both sites match;
ensure the identifier is consistent across the file.
| static has_role = function(role){ | ||
| for (var i=0;i<array_length(units);i++){ | ||
| if (units.role() == role){ | ||
| return true; | ||
| } | ||
| } | ||
|
|
||
| return false; | ||
| } | ||
|
|
||
| static has_base_group = function(group){ | ||
| for (var i=0;i<array_length(units);i++){ | ||
| if (units.base_group == group){ | ||
| return true; | ||
| } | ||
| } | ||
|
|
||
| return false; | ||
| } | ||
|
|
||
| static has_allegiance = function(allegiance){ | ||
| for (var i=0;i<array_length(units);i++){ | ||
| if (units.allegiance == allegiance){ | ||
| return true; | ||
| } | ||
| } | ||
| return false; | ||
| } |
There was a problem hiding this comment.
Array element access error shall cause logic failure, Tech-Priest.
The machine spirit perceives that units is an array, yet it is accessed directly as an object on lines 210, 220, and 230. The iterator variable units[i] must be invoked.
🔎 Corrected array traversal
static has_role = function(role){
for (var i=0;i<array_length(units);i++){
- if (units.role() == role){
+ if (units[i].role() == role){
return true;
}
}
return false;
}
static has_base_group = function(group){
for (var i=0;i<array_length(units);i++){
- if (units.base_group == group){
+ if (units[i].base_group == group){
return true;
}
}
return false;
}
static has_allegiance = function(allegiance){
for (var i=0;i<array_length(units);i++){
- if (units.allegiance == allegiance){
+ if (units[i].allegiance == allegiance){
return true;
}
}
return false;
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| static has_role = function(role){ | |
| for (var i=0;i<array_length(units);i++){ | |
| if (units.role() == role){ | |
| return true; | |
| } | |
| } | |
| return false; | |
| } | |
| static has_base_group = function(group){ | |
| for (var i=0;i<array_length(units);i++){ | |
| if (units.base_group == group){ | |
| return true; | |
| } | |
| } | |
| return false; | |
| } | |
| static has_allegiance = function(allegiance){ | |
| for (var i=0;i<array_length(units);i++){ | |
| if (units.allegiance == allegiance){ | |
| return true; | |
| } | |
| } | |
| return false; | |
| } | |
| static has_role = function(role){ | |
| for (var i=0;i<array_length(units);i++){ | |
| if (units[i].role() == role){ | |
| return true; | |
| } | |
| } | |
| return false; | |
| } | |
| static has_base_group = function(group){ | |
| for (var i=0;i<array_length(units);i++){ | |
| if (units[i].base_group == group){ | |
| return true; | |
| } | |
| } | |
| return false; | |
| } | |
| static has_allegiance = function(allegiance){ | |
| for (var i=0;i<array_length(units);i++){ | |
| if (units[i].allegiance == allegiance){ | |
| return true; | |
| } | |
| } | |
| return false; | |
| } |
🤖 Prompt for AI Agents
In
scripts/scr_UnitGroup_and_group_selection/scr_UnitGroup_and_group_selection.gml
around lines 208 to 235, the code iterates over the units array but accesses
properties/methods directly on units instead of the current element; change each
access to use the loop variable element (units[i]) — replace units.role() with
units[i].role(), units.base_group with units[i].base_group, and units.allegiance
with units[i].allegiance so the checks operate on the current array element.
| return match; | ||
| } | ||
|
|
||
| function collect_by_religeon(religion, sub_cult="", location=""){ |
There was a problem hiding this comment.
Typographical error in function nomenclature, Tech-Priest.
The function collect_by_religeon contains a misspelling. The correct form is collect_by_religion. This may impede discoverability.
🔎 Corrected nomenclature
-function collect_by_religeon(religion, sub_cult="", location=""){
+function collect_by_religion(religion, sub_cult="", location=""){📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| function collect_by_religeon(religion, sub_cult="", location=""){ | |
| function collect_by_religion(religion, sub_cult="", location=""){ |
🤖 Prompt for AI Agents
In
scripts/scr_UnitGroup_and_group_selection/scr_UnitGroup_and_group_selection.gml
around line 296, the function name is misspelled as collect_by_religeon; rename
the function declaration to collect_by_religion and update every reference/call
site to the new name, keeping the same parameters and body intact, and adjust
any comments or documentation that mention the old name so all usages match the
corrected identifier.
| if (unit.name()=="")then continue; | ||
| if (unit.religion == religion){ | ||
| if (sub_cult!=""){ | ||
| if (unit.religion_sub_cult != "sub_cult"){ |
There was a problem hiding this comment.
String literal comparison instead of variable reference, Tech-Priest.
Line 305 compares against the literal string "sub_cult" rather than the sub_cult parameter variable. This shall always evaluate false when a sub_cult is provided.
🔎 Corrected comparison
- if (unit.religion_sub_cult != "sub_cult"){
+ if (unit.religion_sub_cult != sub_cult){📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if (unit.religion_sub_cult != "sub_cult"){ | |
| if (unit.religion_sub_cult != sub_cult){ |
🤖 Prompt for AI Agents
In
scripts/scr_UnitGroup_and_group_selection/scr_UnitGroup_and_group_selection.gml
around line 305, the code is comparing unit.religion_sub_cult to the literal
string "sub_cult" which is wrong; change the comparison to use the variable
sub_cult (no quotes) so it reads unit.religion_sub_cult != sub_cult, ensuring
you reference the parameter/variable rather than the literal; if necessary
ensure sub_cult is in scope and handle nil/undefined values consistently (e.g.,
use explicit checks) before comparing.
| last_turn_check = 0 | ||
| last_turn_image_check = -1; |
There was a problem hiding this comment.
Duplicate initialization detected.
Tech-Priest, last_turn_check is initialized twice—at line 24 and again at line 56. This redundancy pollutes the sacred code. Remove the duplicate to maintain purity.
🔎 Proposed purification
-last_turn_check = 0
last_turn_image_check = -1;📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| last_turn_check = 0 | |
| last_turn_image_check = -1; | |
| last_turn_image_check = -1; |
🤖 Prompt for AI Agents
In objects/obj_en_fleet/Create_0.gml around lines 56 to 57, there is a duplicate
initialization of last_turn_check (it was already set at line 24); remove the
redundant assignment (the lines "last_turn_check = 0" and the accompanying
"last_turn_image_check = -1;" if that one is also duplicated) at lines 56-57 so
the variable is only initialized once (keep the original initialization at line
24), preserving surrounding formatting and semicolons.
| if (struct_exists(save_data, "events")){ | ||
| for (var i=0;i<array_length(save_data.events);i++){ | ||
| var _saved_event = save_data.events[i]; | ||
| var _event = new FleetEvent(); | ||
| with (_event){ | ||
| move_data_to_current_scope(_saved_event); | ||
| } | ||
| array_push(events, _event); | ||
| } | ||
|
|
||
| } |
There was a problem hiding this comment.
FleetEvent construction without required data detected.
Tech-Priest, the invocation at line 172 creates new FleetEvent() without the expected _event_data argument. The constructor at scr_fleet_events.gml line 10 sets self.fleetevent_data = _event_data, which will be undefined when called this way.
While move_data_to_current_scope at line 174 may populate the struct, fleetevent_data will remain as the original undefined value. If any code references fleetevent_data, corruption will occur.
🔎 Proposed sanctification
- var _event = new FleetEvent();
- with (_event){
- move_data_to_current_scope(_saved_event);
- }
+ var _event = new FleetEvent(_saved_event);
+ _event.load_json_data(_saved_event);Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In objects/obj_en_fleet/Create_0.gml around lines 169-179, the code calls new
FleetEvent() without supplying the required _event_data so fleetevent_data
remains undefined; fix this by passing the saved struct into the constructor
(e.g., new FleetEvent(_saved_event)) so fleetevent_data is initialized
correctly, and you can keep or remove the subsequent move_data_to_current_scope
call as needed (if you keep it, ensure it does not rely on fleetevent_data being
set elsewhere).
| switch(owner){ | ||
| case eFACTION.Ork: | ||
| var _has_warboss =false; | ||
| var _has_warboss =false; | ||
| if (fleet_has_cargo("ork_warboss")){ | ||
| draw_icon = true; | ||
| _has_warboss = true; | ||
| } | ||
| break; | ||
| } |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Variable scope anomaly detected.
Tech-Priest, _has_warboss is declared at line 69 within the case eFACTION.Ork block, yet it is accessed at line 159 in a separate switch statement that only executes when owner = eFACTION.Ork. While GML's permissive nature prevents catastrophic failure, explicit initialization outside the switch would strengthen the code's fortifications.
🔎 Proposed strengthening
switch(owner){
+ var _has_warboss = false;
case eFACTION.Ork:
- var _has_warboss =false;
if (fleet_has_cargo("ork_warboss")){Also applies to: 157-163
🤖 Prompt for AI Agents
In objects/obj_en_fleet/Draw_0.gml around lines 67-75 (and similarly for
157-163), the local variable _has_warboss is declared inside the Ork case and
later read elsewhere, risking undefined state; move the declaration and
initialization (var _has_warboss = false) to before the switch so it is in scope
and defaults to false, then inside the Ork case set _has_warboss = true when
cargo is present and remove the inner var keyword so the later switch can
reliably read the variable.
| var _sprite = ds_map_find_value(global.en_fleet_sprites, uid) | ||
| draw_sprite_ext(_sprite, 0, _scale_x_pos-(24*scale) , _scale_y_pos-(24*scale), scale, scale, 1, c_white, 1); |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Potential undefined sprite access.
Tech-Priest, the sprite retrieval at line 194 lacks a defensive check. If the uid is absent from global.en_fleet_sprites (due to race conditions or initialization failures), _sprite will be undefined, and draw_sprite_ext will fail.
Consider adding a guard:
🔎 Proposed fortification
var _sprite = ds_map_find_value(global.en_fleet_sprites, uid)
+if (!sprite_exists(_sprite)){
+ exit;
+}
draw_sprite_ext(_sprite, 0, _scale_x_pos-(24*scale) , _scale_y_pos-(24*scale), scale, scale, 1, c_white, 1);🤖 Prompt for AI Agents
In objects/obj_en_fleet/Draw_0.gml around lines 194-195, the code reads a sprite
with ds_map_find_value(global.en_fleet_sprites, uid) and immediately calls
draw_sprite_ext, which can crash if the map lookup returns undefined/noone; add
a defensive check before drawing: verify the map contains the uid (ds_map_exists
or check _sprite != undefined/noone/-1 depending on your engine version) and
only call draw_sprite_ext when the sprite is valid, otherwise skip drawing or
use a known fallback sprite and optionally log a warning.
| //TODO bottle these into a constructor for re-use | ||
| draw_sprite_ext(spr_servo_left_arm, 0,27+_screen_width,165+_screen_height/3, 2, 2, 0, c_white, 1); | ||
| draw_sprite_ext(spr_servo_right_arm, 0,27,165+_screen_height/3, 2, 2, 0, c_white, 1); | ||
| draw_sprite_ext(spr_servo_skull_head, 0,27+_screen_width/2,165, 2, 2, 0, c_white, 1); |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
TODO detected in the sacred manuscripts.
Tech-Priest, the Machine Spirit has noted this TODO at line 111 regarding bottling servo-skull sprites into a constructor. Shall this cogitation-task be enshrined in a GitHub issue for the Cult Mechanicus to address in due time?
🤖 Prompt for AI Agents
In objects/obj_star_select/Draw_64.gml around lines 111 to 114, there are three
repeated draw_sprite_ext calls with similar parameters and a TODO to "bottle
these into a constructor"; replace the duplicated logic by creating a reusable
function (e.g., draw_servo_sprite or draw_sprite_scaled) that accepts sprite id,
image_index, x_offset, y_offset, scale_x, scale_y, rotation, color, alpha and
call it for each servo-skull position; update the three call sites to invoke
that function with the appropriate offsets (27+_screen_width / 27 /
27+_screen_width/2 and their y values) so the drawing code is centralized and
easy to reuse.
| // increasing necrons | ||
| if (array_length(features) != 0) { | ||
| var has_awake_tomb = false, | ||
| nfleet = 0; | ||
| if (awake_tomb_world(features) == 1) { | ||
| has_awake_tomb = true; | ||
| } | ||
| if (has_awake_tomb) { | ||
| if (planet_forces[eFACTION.Necrons] < 3) { | ||
| planet_forces[eFACTION.Necrons] += 2; | ||
| } else if (planet_forces[eFACTION.Necrons] < 6) { | ||
| planet_forces[eFACTION.Necrons] += 1; | ||
| } | ||
| } | ||
| if (sabotage_force && irandom(2) < 2) { | ||
| planet_forces[eFACTION.Necrons]--; | ||
| scr_event_log("green", $"sabotage force on {name()} disrupts necron forces", name); | ||
| } | ||
|
|
||
| if (has_awake_tomb) { | ||
| // Necron fleets, woooo | ||
| //necrons kill populatin | ||
| if ((population > 0) && (player_forces + pdf + guardsmen + planet_forces[eFACTION.Tyranids] == 0)) { | ||
| population = population * 0.75; | ||
| if ((large_population == 0) && (population <= 5000)) { | ||
| population = 0; | ||
| } | ||
| } | ||
|
|
||
| var fleet_spawn_chance = roll_dice_chapter(1, 100, "high"); | ||
| onceh = 0; | ||
|
|
||
| if (fleet_spawn_chance <= 15) { | ||
| if (system.present_fleet[eFACTION.Necrons] > 0) { | ||
| //if necron fleet | ||
| necron_fleet = instance_nearest(x, y, obj_en_fleet); | ||
|
|
||
| if (necron_fleet.owner == eFACTION.Necrons) { | ||
| if (necron_fleet.escort_number < necron_fleet.capital_number * 1.5) { | ||
| necron_fleet.escort_number += 2; | ||
| } else if (necron_fleet.frigate_number < necron_fleet.capital_number * 3) { | ||
| necron_fleet.frigate_number += 1; | ||
| } else { | ||
| necron_fleet.capital_number += 1; | ||
| } | ||
| } | ||
| } else if (system.present_fleet[eFACTION.Necrons] == 0) { | ||
| necron_fleet = instance_create(x, y, obj_en_fleet); | ||
| necron_fleet.owner = eFACTION.Necrons; | ||
| necron_fleet.capital_number = 1; | ||
| necron_fleet.sprite_index = spr_fleet_necron; | ||
| necron_fleet.image_speed = 0; | ||
| necron_fleet.image_index = 1; | ||
| system.present_fleet[eFACTION.Necrons] += 1; | ||
| } | ||
| var enemy_fleets = 0; | ||
| with(necron_fleet) { | ||
| if (owner == eFACTION.Necrons) { | ||
| var ii = 0; | ||
| ii += capital_number; | ||
| ii += round((frigate_number / 2)); | ||
| ii += round((escort_number / 4)); | ||
| if (ii <= 1) { | ||
| ii = 1; | ||
| } // image_index=max(8,round(ii)); | ||
|
|
||
| if ((ii >= 7) && (capital_number > 1)) { | ||
| for (var fleet_n = 1; fleet_n <= 10; fleet_n++) { | ||
| if (orbiting.present_fleet[fleet_n] > 0) { | ||
| enemy_fleets++; | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| if (enemy_fleets > 0) { | ||
| var necron_fleet2; | ||
| necron_fleet2 = instance_create(x, y, obj_en_fleet); | ||
| necron_fleet2.owner = eFACTION.Necrons; | ||
| necron_fleet2.sprite_index = spr_fleet_necron; | ||
| // necron_fleet2.image_index=0; | ||
| necron_fleet.image_speed = 0; | ||
| necron_fleet2.capital_number = 1; | ||
| necron_fleet2.frigate_number = round(necron_fleet.frigate_number / 2); | ||
| necron_fleet2.escort_number = round(necron_fleet.escort_number / 2); | ||
| system.present_fleet[eFACTION.Necrons] += 1; | ||
|
|
||
| necron_fleet.capital_number -= 1; | ||
| necron_fleet.frigate_number -= necron_fleet2.frigate_number; | ||
| necron_fleet.escort_number -= necron_fleet2.escort_number; | ||
| var nearest_planet_coords = [0, 0]; | ||
| var found_near_planet = false; | ||
| with(obj_star) { | ||
| if (present_fleet[eFACTION.Necrons] == 0) { | ||
| if (!array_contains(p_type, "Dead")) { | ||
| for (var plan = 1; plan <= planets; plan++) { | ||
| if (p_owner[plan] <= 5) { | ||
| found_near_planet = true; | ||
| nearest_planet_coords = [x, y]; | ||
| break; | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| if (found_near_planet) { | ||
| var tgt1, tgt2; | ||
|
|
||
| necron_fleet2.action_x = nearest_planet_coords[0]; | ||
| necron_fleet2.action_y = nearest_planet_coords[1]; | ||
| with (necron_fleet2){ | ||
| set_fleet_movement(); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Consider extraction of Necron awakening logic, Tech-Priest.
The Necron tomb world awakening and fleet manifestation sequence (lines 1517-1635) comprises 118 lines within the broader end-of-turn ritual. The machine spirit suggests consecrating this as a separate static method end_turn_necron_awakening to reduce cognitive burden and align with the pattern established by other faction-specific ceremonies.
🤖 Prompt for AI Agents
In scripts/scr_PlanetData/scr_PlanetData.gml around lines 1517-1635, the
118-line Necron tomb world awakening and fleet-spawn logic should be extracted
into a new static function end_turn_necron_awakening to reduce code size and
mirror other faction handlers; move all logic inside those lines into that
function, determine and pass only the needed inputs (e.g., self/planet context,
features, name, x, y, population, large_population, planet_forces,
player_forces, pdf, guardsmen, sabotage_force, system reference, etc.), have the
function mutate the planet/system objects or return any changed primitives
(population, planet_forces entries, system.present_fleet counts) so existing
state updates remain identical, replace the original block with a single call to
end_turn_necron_awakening(...), and ensure instance_create/with semantics and
local variables (necron_fleet, necron_fleet2, enemy_fleets,
nearest_planet_coords, found_near_planet) are confined to the new function to
avoid scope leaks and preserve behavior and randomness.
| // if ((action_score > 100) && (action_score <= 200)) { siz_penalty = 75; } | ||
| // if (action_score > 200) { siz_penalty = 125; } | ||
|
|
||
| var spec1=0,spec2=0,txt=""; // TODO consider making it a battle with Planetary governor's guards |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
TODO incantation regarding governor guard combat, Tech-Priest.
The notation suggests transforming governor assassination into a proper battle sequence with planetary defenders. Shall the machine spirit inscribe this enhancement into the issue-tracking repository?
| if (!population_large){ | ||
| pop_after=round(pop_after); | ||
| } | ||
|
|
||
|
|
||
| var _displayed_population = star.p_large[planet] == 1 ? $"{pop_before} billion" : scr_display_number(floor(pop_before)); | ||
| var _displayed_killed = star.p_large[planet] == 1 ? $"{kill} billion" : scr_display_number(floor(kill)); | ||
| txt1 += $"##The world had {_displayed_population} Imperium subjects. {_displayed_killed} were purged over the duration of the bombardment.##Heresy has fallen down to {max(0, heres_after)}%."; | ||
| var _displayed_population = display_population(); | ||
| var _displayed_killed = large_population ? $"{kill} billion" : scr_display_number(floor(kill)); |
There was a problem hiding this comment.
❓ Verification inconclusive
Script executed:
#!/bin/bash
# Search for both variable names in the scr_purge_world file
rg -n "population_large|large_population" scripts/scr_purge_world/scr_purge_world.gml -A 1 -B 1Repository: Adeptus-Dominus/ChapterMaster
Repository: Adeptus-Dominus/ChapterMaster
Exit code: 0
stdout:
92-
93: if (!population_large){
94- pop_after=round(pop_after);
--
98- var _displayed_population = display_population();
99: var _displayed_killed = large_population ? $"{kill} billion" : scr_display_number(floor(kill));
100- txt1 += $"\n\nThe world had {_displayed_population} Imperium subjects. {_displayed_killed} were purged over the duration of the bombardment.\n\nHeresy has fallen down to {max(0, heres_after)}%.";
--
156-
157: max_kill = population_large_conversion(12000) *action_score;
158-
--
163-
164: if (!population_large){
165- pop_after=max(_pop_before-kill,0);
166- }
167: if (large_population){
168- pop_after=_pop_before;
--
197- }
198: if (!population_large){
199- pop_after=round(pop_after);
--
201-
202: if (!population_large){
203- txt1+="\n\nThe planet had a population of "+string(scr_display_number(floor(_pop_before)))+" and "+string(scr_display_number(floor(kill)))+" were purged over the duration of the cleansing.\n\nHeresy has fallen down to "+string(max(0,heres_after))+"%.";
--
235-
236: if (!population_large) {
237- max_kill=action_score*30;// Population if normal
238- }
239: if (large_population) {
240- max_kill=0;// Population if large
--
247-
248: if (!population_large) {
249- pop_after=max(_pop_before-kill,0);
--
256-
257: if (!population_large) {
258- pop_after=round(pop_after);
--
260-
261: if (!population_large) {
262- txt1+=$"\n\nThe planet had a population of "+string(scr_display_number(floor(_pop_before)))+" and "+string(scr_display_number(floor(kill)))+" die over the duration of the search.\n\nHeresy has fallen to "+string(max(0,heres_after))+"%.";
263- }
264: if (large_population) {
265- txt1+=$"\n\nThe planet had a population of {_pop_before} billion and {action_score*30} die over the duration of the search.\n\nHeresy has fallen to "+string(max(0,heres_after))+"%.";
--
289- }
290: if (action_type==DropType.PurgeSelective && !population_large){
291- set_population(pop_after);
Script executed:
#!/bin/bash
# Get the full file to understand context and variable declarations
wc -l scripts/scr_purge_world/scr_purge_world.gmlRepository: Adeptus-Dominus/ChapterMaster
Repository: Adeptus-Dominus/ChapterMaster
Exit code: 0
stdout:
317 scripts/scr_purge_world/scr_purge_world.gml
Script executed:
#!/bin/bash
# Check for variable declarations and initializations
rg -n "^\s*(var|population_large|large_population)\s*=" scripts/scr_purge_world/scr_purge_world.gmlRepository: Adeptus-Dominus/ChapterMaster
Repository: Adeptus-Dominus/ChapterMaster
Exit code: 1
Variable naming inconsistency corrupts the sacred protocols.
Tech-Priest, the machine spirit perceives a troubling duality in the nomenclature of the population threshold. The code employs both population_large (inverted in conditionals at lines 93, 164, 198, 202, 236, 248, 257, 261, 290) and large_population (at lines 99, 167, 239, 264) to represent the same logical concept—a most grievous violation of coherence.
These variables serve complementary conditions within mirrored conditional branches, yet their nomenclature contradicts itself. Unify this nomenclature to a singular truth lest future Tech-Priests stumble upon this contradiction in ritual maintenance.
Also applies to: 164-169, 236-241, 248-266
🤖 Prompt for AI Agents
scripts/scr_purge_world/scr_purge_world.gml lines 93-99, 164-169, 198-202,
236-241, 248-266: the file mixes two names for the same boolean
(population_large vs large_population); pick one canonical name (e.g.,
population_large), then replace all occurrences of the other name in these
ranges and elsewhere in the file to match the chosen name, update any related
conditional checks and displayed variables (e.g., the ternary that sets
_displayed_killed) to use the canonical name, ensure the variable
declaration/initialization uses the same name, and run a project-wide search to
confirm no remaining mismatched references.
| if (current_owner=2 && obj_controller.faction_status[2]!="War"){ | ||
| if (planet_type="Temperate" || planet_type="Hive" || planet_type="Desert"){ | ||
| var _disp_hit = -10; | ||
| if (star.p_type[planet]="Temperate") then _disp_hit = -5; | ||
| if (star.p_type[planet]="Desert") then _disp_hit = -3; | ||
| if (planet_type="Temperate"){ | ||
| _disp_hit = -5; | ||
| } | ||
| if (planet_type="Desert"){ | ||
| _disp_hit = -3; | ||
| } | ||
|
|
||
| scr_audience(eFACTION.Imperium, "bombard_angry", _disp_hit, "", 0, 0); | ||
| } | ||
| } | ||
| } | ||
| if (star.p_owner[planet]=3) and (obj_controller.faction_status[3]!="War"){ | ||
| if (current_owner=3 && obj_controller.faction_status[3]!="War"){ | ||
|
|
||
| if (star.p_type[planet]="Forge") then _disp_hit =-15; | ||
| if (star.p_type[planet]="Ice") then _disp_hit =-7; | ||
| if (planet_type="Forge"){ | ||
| _disp_hit =-15; | ||
| } | ||
| if (planet_type="Ice"){ | ||
| _disp_hit =-7; | ||
| } | ||
| scr_audience(eFACTION.Inquisition, "bombard_angry", _disp_hit, "", 0, 0); | ||
|
|
||
| } |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Assignment-as-comparison detected in conditional blocks.
Tech-Priest, the Machine Spirit observes the use of = rather than == for comparisons at lines 103, 104, 106, 109, 117, 119, 122. While GML tolerates this heresy, it creates ambiguity for future Tech-Adepts maintaining the code. The sacred standard is == for equality checks.
Does this pattern exist throughout the codebase, or should these be standardised?
🤖 Prompt for AI Agents
In scripts/scr_purge_world/scr_purge_world.gml around lines 103 to 127 there are
assignment-into-condition mistakes using = instead of the equality operator ==
(at the lines checking current_owner and planet_type), which causes unintended
assignments; update each conditional to use == for comparisons (e.g.,
current_owner == 2, planet_type == "Temperate", etc.), ensure _disp_hit is
declared/initialized before use where needed, run a project-wide search for
other occurrences of single = inside if/while conditions and standardize them to
==, then test the game logic paths to confirm behavior is unchanged.
| case EVENT.enemy: | ||
| if(scr_has_adv("Scavangers")){ | ||
| events_share[i] += 2; | ||
| events_total += 2; | ||
| } | ||
|
|
||
| break; |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Empty case block detected in the sacred logic.
Tech-Priest, this case for EVENT.enemy contains naught but void. The Machine Spirit queries: was this emptiness intentional, or has sacred code been excised? If deliberate, a comment would illuminate the purpose for future Tech-Adepts.
🤖 Prompt for AI Agents
In scripts/scr_random_event/scr_random_event.gml around lines 148-150 the case
for EVENT.enemy is an empty block with no comment or handling; either implement
the intended behavior for enemy events (e.g., call the enemy event handler, set
event state, spawn enemies, or update relevant variables) or, if intentionally
left empty, add a concise explanatory comment like "Intentionally no-op: enemies
handled elsewhere" so future readers know this is deliberate. Ensure the chosen
fix follows surrounding code patterns (use existing helper functions or state
changes used by other cases) and preserves switch fallthrough semantics if
applicable.
|
This PR is marked as stale, because it has been open for 7 days with no activity. |
Purpose and Description
#improvements
Testing done
Related things and/or additional context